package com.tj.demo.util.cases;

import cn.hutool.core.io.IoUtil;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.tj.demo.util.toolkit.FuncUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName: testUtil
 * @Author: TanJun
 * @Date: 2021/5/15 17:05
 * @Description:
 * @Version: 1.0
 * @Copyright: 常见工具案例
 */
public class ToolCase {
    static Logger logger = LoggerFactory.getLogger(ToolCase.class);

    public static void main(String[] args) {
        common();
    }

    /**
     * 常见方法  123
     */
    public static void common() {
        StringBuilder result = new StringBuilder();
        BufferedReader bufrIn = null;
        BufferedReader bufrError = null;
        try {
            //linux执行命令
            String cmd = "chmod 777" + "/data/file/girb";
            //执行命令 返回一个子进程对象（命令在子进程中执行）
            Process process = Runtime.getRuntime().exec(cmd);
            new Thread() {
                @Override
                public void run() {
                    BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    String line = null;
                    try {
                        while ((line = in.readLine()) != null) {
                            logger.info("datax执行的结果为: " + line);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        IoUtil.close(in);
                    }
                }
            }.start();

            new Thread() {
                @Override
                public void run() {
                    BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                    String line = null;
                    StringBuilder result = new StringBuilder();
                    try {
                        while ((line = err.readLine()) != null) {
                            result.append(line);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        IoUtil.close(err);
                    }
                }
            }.start();
        } catch (IOException e) {
            e.printStackTrace();
        }


//        /***
//         * 1.主进程中调用Runtime.exec会创建一个子进程，用于执行shell脚本。子进程创建后会和主进程分别独立运行。
//         * 2.主进程需要等待脚本执行完成，然后对脚本返回值或输出进行处理，主进程调用Process.waitfor等待子进程完成
//         * 3.主进程中可以通过Process.getInputStream和Process.getErrorStream获取并处理
//         * 4.子进程不断向主进程输送数据
//         * 5.最后返回"0"结果,处理结果
//         *
//         * 问题
//         * 步骤4中
//         *      子进程和主进程之间的缓冲区塞满后，子进程不能继续写数据，然后也会挂起
//         *      子进程等待主进程读取数据，主进程等待子进程结束，两个进程相互等待，最终导致死锁
//         *
//         * **/
//        StringBuilder result = new StringBuilder();
//        Process process = null;
//        BufferedReader bufrIn = null;
//        BufferedReader bufrError = null;
//        try{
//            //linux执行命令
//            String cmd = "chmod 777" + "/data/file/girb";
//            //执行命令 返回一个子进程对象（命令在子进程中执行）
//            process = Runtime.getRuntime().exec(cmd);
//            // 方法阻塞, 等待命令执行完成（成功会返回0）
//            int i = process.waitFor();
//
//            // 获取命令执行结果, 有两个结果: 正常的输出 和 错误的输出（PS: 子进程的输出就是主进程的输入）
//            bufrIn = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
//            bufrError = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
//            process.destroy();
//
//            // 读取输出
//            String line = null;
//            while ((line = bufrIn.readLine()) != null) {
//                result.append(line).append('\n');
//            }
//            while ((line = bufrError.readLine()) != null) {
//                result.append(line).append('\n');
//            }
//        } catch (IOException e){
//            e.printStackTrace();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        } finally {
//            //销毁Process对象
//            process.destroy();
//            /***
//             * 解决常见io关闭问题
//             * 1.被关闭对象为空
//             * 2.对象关闭失败（或对象已关闭）
//             *
//             * **/
//            IoUtil.close(bufrIn);
//            IoUtil.close(bufrError);
//        }

        logger.info("common方法体执行完成");
    }

    /**
     * Java8常见的Map及List方法处理
     * Collectors(toList()、toSet()、toCollection()、joining()、partitioningBy()、collectingAndT)
     * toList：将数据收集进一个列表(Stream 转换为 List，允许重复值，有顺序)
     * toSet：将数据收集进一个集合(Stream 转换为 Set，不允许重复值，没有顺序)
     * toCollection：自定义的实现Collection的数据结构收集 如：list.stream().collect(Collectors.toCollection(TreeSet::new))
     * joining：实现连接的 无参数（默认自动连接）、一个参数（分隔符连接）、三个参数（分隔符，前缀，后缀）
     * collectingAndThen：收集之后继续做一些处理
     */
    public static void mapList() {
        //实体类初始
        List<List<UserBean>> lists = UserBean.listInit();
        List<UserBean> list = lists.get(0);
        List<UserBean> listNew = lists.get(1);

        /***
         * 1.list过滤
         *
         * **/
        List<UserBean> listGl = list.stream().filter(item -> item.getGender().equals("男")).collect(Collectors.toList());

        /***
         * 2.list取出第一个对象
         *
         * **/
        UserBean userBean = list.stream().findFirst().orElse(null);

        /***
         * 3.map(T -> R) maping(T -> R) 类似类型转换
         * 集合获取指定的字段数组 在此基础上可以做交集、差集等拓展
         * **/
        List<Integer> listIds = list.stream().map(UserBean::getId).collect(Collectors.toList());

        /***
         * 4.交集、差集、并集、去重并集
         * 1)交集 listJi
         * 2)差集 listCj
         * 3)并集 listBj
         * 4)去重并集 listQCBJOne  listQCBJTwo
         *    distinct按照整个对象去重
         *    filter按照某个字段去重
         * **/
        List<UserBean> listJj = list.stream().filter(item -> listNew.stream().map(itemNew -> itemNew.getId()).collect(Collectors.toList()).contains(item.getId())).collect(Collectors.toList());
        List<UserBean> listCj = list.stream().filter(item -> !listNew.stream().map(itemNew -> itemNew.getId()).collect(Collectors.toList()).contains(item.getId())).collect(Collectors.toList());

        List<UserBean> listBj = new ArrayList<>();
        listBj.addAll(listJj);
        listBj.addAll(listCj);
        List<UserBean> listQCBJOne = listBj.stream().distinct().collect(Collectors.toList());
        listBj.addAll(list);
        List<UserBean> listQCBJTwo = listBj.stream().filter(FuncUtil.distinctByKey(item -> item.getId())).collect(Collectors.toList());

        /***
         * 5.list排序
         * 1）Comparator排序
         * 2）compareTo排序
         *
         * **/
        //1)用匿名函数Comparator
        Collections.sort(list, new Comparator<UserBean>() {
            @Override
            public int compare(UserBean o1, UserBean o2) {
                return o2.getId() - o1.getId();
            }
        });

        //2)函数式编程  thenComparing 先升序之后利用 reversed进行反序
        list.sort(Comparator.comparing(UserBean::getId).thenComparing(UserBean::getSalary).reversed());

        //3)lambda表达式可以替代匿名内部的写法
        Collections.sort(list, (a, b) -> b.getId().compareTo(a.getId()));

        /***
         * 6.分组、转Map
         * 1) 分组 listFz
         * 2) List转Map listToMap
         * 3) 拓展 分组后选取每组第一条数据（再次拓展分组里面的排序后的第一条数据）
         *      1）listFzTz list分组后取每组list第一条数据 （技巧：先按照想要的排列顺序-->再分组选取第一条数据）
         *      2) listFzPxTz 分组-->每组list排序后选取第一条数据
         *      3) listFiledFzPxTz/listFiledFzPxTz1 分组-->每组list排序后选取第一条数据的"某个字段"
         *
         * **/
        Map<String, List<UserBean>> listfz = list.stream().collect(Collectors.groupingBy(UserBean::getDepart));
        Map<Integer, UserBean> listToMap = list.stream().collect(Collectors.toMap(UserBean::getId, item -> item));
        Map<Object, UserBean> listFzTz = list.stream().collect(Collectors.groupingBy(UserBean::getDepart, Collectors.collectingAndThen(Collectors.toList(), itemList -> itemList.get(0))));
        Map<String, String> listFiledFzPxTz = list.stream().collect(Collectors.groupingBy(UserBean::getDepart, Collectors.collectingAndThen(Collectors.toList(), itemList -> itemList.get(0).getName())));
        Map<String, String> listFiledFzPxTz1 = list.stream().collect(Collectors.groupingBy(UserBean::getDepart, Collectors.mapping(p -> p.getName(), Collectors.collectingAndThen(Collectors.toList(), itemList -> itemList.get(0)))));

        /***
         * 7.常见计算类型
         * 1) 基本类型求和 sumJb
         * 2) 基本值的最大值 maxJb
         * 3) 基本类型平均值 averageJb
         * 4) BigDecimal求和 sumTs
         *
         * **/
        int sumJb = list.stream().mapToInt(UserBean::getAge).sum();
        Integer maxJb = list.stream().map(UserBean::getAge).max(Integer::compareTo).get();
        double averageJb = list.stream().mapToDouble(UserBean::getAge).average().getAsDouble();
        BigDecimal sumTs = list.stream().map(UserBean::getSalary).reduce(BigDecimal.ZERO, BigDecimal::add);
        logger.info("mapList方法体执行完成");
    }

    /**
     * joiner常见用法
     */

    public static void joiner() {
        //名称集合
        String[] nameArray = {"Google", "Guava", "Java", "Test", null, "Kafka"};

        /***
         * 1.List转数组  String[] nameArray = new String[nameList.size()] --> nameList.toArray(nameArray)
         * 2.数组转List  List<String> nameList = Arrays.asList(nameArray)
         * **/
        List<String> nameList = Arrays.asList(nameArray);
        List<String> nameListFk = Arrays.asList("Google", "Guava", "Java", "Test", "Kafka");

        /***
         * 1.普通连接  joinPtSplic  注意：该方法只支持非空集合
         * 2.跳过空元素  joinTkSplic
         * 3.默认值替换空元素  joinThSplic
         * 4.结果放入StringBuffer  joinBuffer
         * 5.结果放入StringBuider  joinBuider
         * 6.连接Stream  joinStream
         * 7.String转List
         * 8.还可以连接Map
         * 9.Stirng转List  joinStr-->joinList
         * **/
        String joinSplic = Joiner.on("-").join(nameListFk);
        String joinTkSplic = Joiner.on("-").skipNulls().join(nameList);
        String joinThSplic = Joiner.on("-").useForNull("Default").join(nameList);
        try {
            StringBuffer sBufefer = new StringBuffer("src-");
            StringBuffer joinBuffer = Joiner.on("-").useForNull("Default").appendTo(sBufefer, nameList);

            //放入文件中去
            FileWriter fileWriter = new FileWriter(new File("C:\\data\\file\\testFile\\joiner.txt"));
            Joiner.on("-").useForNull("Default").appendTo(fileWriter, nameList);
            fileWriter.flush();
            logger.info("StringBuffer字符,{},joinBuffer字符,{}", sBufefer, joinBuffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        StringBuilder sBuider = new StringBuilder("src-");
        StringBuilder joinBuider = Joiner.on("-").useForNull("Default").appendTo(sBuider, nameList);

        //使用Stream
        String joinStream = nameList.stream().filter(item -> !StringUtils.isEmpty(item)).collect(Collectors.joining("-"));

        String joinStr = "test1,test2,test3";
        List<String> joinList = Splitter.on(",").trimResults().splitToList(joinStr);
        logger.info("Joiner方法体执行完成");
    }
}
